class Dep {
  constructor() {
    this.subscribers = new Set()
  }

  depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect)
    }
  }
  notify() {
    this.subscribers.forEach(effect => effect())
  }
}




let activeEffect = null

function watchEffect(effect) {
  activeEffect = effect
  effect()
  activeEffect = null
}

const targetMap = new WeakMap()

function getDep(target, key) {
  let depsMap = targetMap.get(target)

  if (!depsMap) {
    depsMap = new Map()
    targetMap.set(target, depsMap)
  }

  let dep = depsMap.get(key)
  if (!dep) {
    dep = new Dep()
    depsMap.set(key, dep)
  }
  return dep
}

function reactive(raw) {


  Object.keys(raw).forEach(key => {

    const dep = getDep(raw, key)
    let value = raw[key]

    Object.defineProperty(raw, key, {
      get() {
        dep.depend()
        return value
      },
      set(newValue) {
        if (value!==newValue) {
          value = newValue
          dep.notify()
        }
      }
    })
  })
  return raw
}

const info = reactive({ counter: 100, name: '胭脂' })
const foo = reactive({ height: 1.88 })



watchEffect(() => {
  debugger
  
  console.log('11111',info.counter * 2, info.name)
})

watchEffect(()=> {
  console.log('222222',info.counter * info.counter)
})

watchEffect(()=> {
  console.log('33333',info.counter + 10, info.name)
})

watchEffect(() => {
  console.log('44444',foo.height)
})
 

info.name = 'ddsd'